﻿using Roton.Memory;
using Roton.ZZT;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Roton.Wrapper
{
    /// <summary>
    /// Adapts IThing to a Segment object.
    /// </summary>
    class ThingWrapper : IThing
    {
        private ThingWrapperProperties properties;
        private Segment segment;

        public ThingWrapper(int baseOffset, Segment segment, ThingWrapperProperties properties)
        {
            this.segment = segment;
            properties.OffsetCycle += baseOffset;
            properties.OffsetFollower += baseOffset;
            properties.OffsetInstruction += baseOffset;
            properties.OffsetLeader += baseOffset;
            properties.OffsetLength += baseOffset;
            properties.OffsetP1 += baseOffset;
            properties.OffsetP2 += baseOffset;
            properties.OffsetP3 += baseOffset;
            properties.OffsetPointer += baseOffset;
            properties.OffsetStepX += baseOffset;
            properties.OffsetStepY += baseOffset;
            properties.OffsetUnderColor += baseOffset;
            properties.OffsetUnderID += baseOffset;
            properties.OffsetX += baseOffset;
            properties.OffsetY += baseOffset;
            this.properties = properties;
        }

        public int Cycle
        {
            get
            {
                return segment.Read16(properties.OffsetCycle);
            }
            set
            {
                segment.Write16(properties.OffsetCycle, value);
            }
        }

        public int Follower
        {
            get
            {
                return segment.Read16(properties.OffsetFollower);
            }
            set
            {
                segment.Write16(properties.OffsetFollower, value);
            }
        }

        public int Instruction
        {
            get
            {
                return segment.Read16(properties.OffsetInstruction);
            }
            set
            {
                segment.Write16(properties.OffsetInstruction, value);
            }
        }

        public int Leader
        {
            get
            {
                return segment.Read16(properties.OffsetLeader);
            }
            set
            {
                segment.Write16(properties.OffsetLeader, value);
            }
        }

        public int Length
        {
            get
            {
                return segment.Read16(properties.OffsetLength);
            }
            set
            {
                segment.Write16(properties.OffsetLength, value);
            }
        }

        public ILocation Location
        {
            get
            {
                return new LocationWrapper(properties.OffsetX, segment);
            }
        }

        public int P1
        {
            get
            {
                return segment.Read8(properties.OffsetP1);
            }
            set
            {
                segment.Write8(properties.OffsetP1, value);
            }
        }

        public int P2
        {
            get
            {
                return segment.Read8(properties.OffsetP2);
            }
            set
            {
                segment.Write8(properties.OffsetP2, value);
            }
        }

        public int P3
        {
            get
            {
                return segment.Read8(properties.OffsetP3);
            }
            set
            {
                segment.Write8(properties.OffsetP3, value);
            }
        }

        public int Pointer
        {
            get
            {
                return segment.Read32(properties.OffsetPointer);
            }
            set
            {
                segment.Write32(properties.OffsetPointer, value);
            }
        }

        public int StepX
        {
            get
            {
                return segment.Read16(properties.OffsetStepX);
            }
            set
            {
                segment.Write16(properties.OffsetStepX, value);
            }
        }

        public int StepY
        {
            get
            {
                return segment.Read16(properties.OffsetStepY);
            }
            set
            {
                segment.Write16(properties.OffsetStepY, value);
            }
        }

        public int UnderColor
        {
            get
            {
                return segment.Read8(properties.OffsetUnderColor);
            }
            set
            {
                segment.Write8(properties.OffsetUnderColor, value);
            }
        }

        public int UnderID
        {
            get
            {
                return segment.Read8(properties.OffsetUnderID);
            }
            set
            {
                segment.Write8(properties.OffsetUnderID, value);
            }
        }

        public IVector Vector
        {
            get
            {
                return new VectorWrapper(properties.OffsetStepX, segment);
            }
        }

        public int X
        {
            get
            {
                return segment.Read8(properties.OffsetX);
            }
            set
            {
                segment.Write8(properties.OffsetX, value);
            }
        }

        public int Y
        {
            get
            {
                return segment.Read8(properties.OffsetY);
            }
            set
            {
                segment.Write8(properties.OffsetY, value);
            }
        }
    }

    struct ThingWrapperProperties
    {
        public int OffsetCycle;
        public int OffsetFollower;
        public int OffsetInstruction;
        public int OffsetLeader;
        public int OffsetLength;
        public int OffsetP1;
        public int OffsetP2;
        public int OffsetP3;
        public int OffsetPointer;
        public int OffsetStepX;
        public int OffsetStepY;
        public int OffsetUnderColor;
        public int OffsetUnderID;
        public int OffsetX;
        public int OffsetY;
    }
}
